/**
 * jQuery jfUI (drag拖拽)
 * 
 * @author yepp(叶平平)
 * @date 2012-11-13
 * 
 * ***/
;(function($){

	$.fn.jfDrag = function (options)
    {
        return $.jfui.run.call(this, "jfDrag", arguments,
        {
            idAttrName: 'jfuidragid', hasElement: false, propertyToElement: 'target'
        }
        );
    };
	
	 $.fn.jfGetDragManager = function ()
    {
        return $.jfui.run.call(this, "jfGetDragManager", arguments,
        {
            idAttrName: 'jfuidragid', hasElement: false, propertyToElement: 'target'
        });
    };
	
	$.jfDefaults.Drag = {
		onStartDrag: false,
        onDrag: false,
        onStopDrag: false,
        handler: null,
        //代理 拖动时的主体,可以是'clone'或者是函数,放回jQuery 对象
        proxy: true,
        revert: false,
        animate: true,
        onRevert: null,
        onEndRevert: null,
        //接收区域 jQuery对象或者jQuery选择字符
        receive: null,
        //进入区域
        onDragEnter: null,
        //在区域移动
        onDragOver: null,
        //离开区域
        onDragLeave: null,
        //在区域释放
        onDrop: null,
        disabled: false,
        proxyX: null,     //代理相对鼠标指针的位置,如果不设置则对应target的left
        proxyY: null
	};
	
	$.jfui.controls.Drag = function(options){
		$.jfui.controls.Drag.base.constructor.call(this, null, options);
	};
	
	$.jfui.controls.Drag.jfExtend($.jfui.core.UIComponent,{
		__getType : function(){
			return 'Drag';
		},
		__idPrev : function(){
			return 'Drag';
		},
		_render : function(){
			var g = this, p = this.options;
            this.set(p);
            g.cursor = "move";
            g.handler.css('cursor', g.cursor);
            g.handler.bind('mousedown.drag', function (e)
            {
                if (p.disabled) return;
                if (e.button == 2) return;
                g._start.call(g, e);
            }).bind('mousemove.drag', function ()
            {
                if (p.disabled) return;
                g.handler.css('cursor', g.cursor);
            });
		},
		_rendered :function(){
			 this.options.target.jfuidragid = this.id;
		},
		_start : function(e){
			var g = this, p = this.options;
            if (g.reverting) return;
            if (p.disabled) return;
            g.current = {
                target: g.target,
                left: g.target.offset().left,
                top: g.target.offset().top,
                startX: e.pageX || e.screenX,
                startY: e.pageY || e.clientY
            };
            if (g.trigger('startDrag', [g.current, e]) == false) return false;
            g.cursor = "move";
            g._createProxy(p.proxy, e);
            //代理没有创建成功
            if (p.proxy && !g.proxy) return false;
            (g.proxy || g.handler).css('cursor', g.cursor);
            $(document).bind("selectstart.drag", function () { return false; });
            $(document).bind('mousemove.drag', function ()
            {
                g._drag.apply(g, arguments);
            });
            $.jfui.draggable.dragging = true;
            $(document).bind('mouseup.drag', function ()
            {
                 $.jfui.draggable.dragging = false;
                g._stop.apply(g, arguments);
            });
		},
		_drag : function(e){
			var g=this,p=this.options;
			if(!g.current){
				return;
			}
			var pageX = e.pageX || e.screenX;
			var pageY = e.pageY || e.screenY;
			g.current.diffX = pageX-g.current.startX;
			g.current.diffY = pageY-g.current.startY;
			(g.proxy || g.handler).css('cursor', g.cursor);
			if(g.receive){
				 g.receive.each(function (i, obj){
                    var receive = $(obj);
                    var xy = receive.offset();
                    if (pageX > xy.left && pageX < xy.left + receive.width() && pageY > xy.top && pageY < xy.top + receive.height()){
                        if (!g.receiveEntered[i]){
                            g.receiveEntered[i] = true;
                            g.trigger('dragEnter', [obj, g.proxy || g.target, e]);
                        }else{
                            g.trigger('dragOver', [obj, g.proxy || g.target, e]);
                        }
                    } else if (g.receiveEntered[i]){
                        g.receiveEntered[i] = false;
                        g.trigger('dragLeave', [obj, g.proxy || g.target, e]);
                    }
                });
			}
			if (g.hasBind('drag')){
                if (g.trigger('drag', [g.current, e]) != false){
                    g._applyDrag();
                }else{
                    g._removeProxy();
                }
            }else{
                g._applyDrag();
            }
		},
		_stop : function(e){
			var g = this, p = this.options;
            $(document).unbind('mousemove.drag');
            $(document).unbind('mouseup.drag');
            $(document).unbind("selectstart.drag");
            if (g.receive){
                g.receive.each(function (i, obj){
                    if (g.receiveEntered[i]){
                        g.trigger('drop', [obj, g.proxy || g.target, e]);
                    }
                });
            }
            if (g.proxy){
                if (p.revert){
                    if (g.hasBind('revert')){
                        if (g.trigger('revert', [g.current, e]) != false){
                        	g._revert(e);
                        }else{
                        	g._removeProxy();
                        }     
                    } else{
                        g._revert(e);
                    }
                }else{
                    g._applyDrag(g.target);
                    g._removeProxy();
                }
            }
            g.cursor = 'move';
            g.trigger('stopDrag', [g.current, e]);
            g.current = null;
            g.handler.css('cursor', g.cursor);
		},
		_revert: function (e)
        {
            var g = this;
            g.reverting = true;
            g.proxy.animate({
                left: g.current.left,
                top: g.current.top
            },function (){
                g.reverting = false;
                g._removeProxy();
                g.trigger('endRevert', [g.current, e]);
                g.current = null;
            });
        },
        _applyDrag: function (applyResultBody)
        {
            var g = this, p = this.options;
            applyResultBody = applyResultBody || g.proxy || g.target;
            var cur = {}, changed = false;
            var noproxy = applyResultBody == g.target;
            if (g.current.diffX){
                if (noproxy || p.proxyX == null){
                	cur.left = g.current.left + g.current.diffX;
                } else{
                	cur.left = g.current.startX + p.proxyX + g.current.diffX;
                }    
                changed = true;
            }
            if (g.current.diffY){
                if (noproxy || p.proxyY == null){
                	 cur.top = g.current.top + g.current.diffY;
                }else{
                	 cur.top = g.current.startY + p.proxyY + g.current.diffY;
                }    
                changed = true;
            }
            if (applyResultBody == g.target && g.proxy && p.animate){
                g.reverting = true;
                applyResultBody.animate(cur, function (){
                    g.reverting = false;
                });
            }else{
                applyResultBody.css(cur);
            }
        },
         _setReceive: function (receive){
            this.receiveEntered = {};
            if (!receive){
            	return;
            }
            if (typeof receive == 'string'){
            	 this.receive = $(receive);
            } else{
            	 this.receive = receive;
            }    
        },
         _setHandler: function (handler) {
            var g = this, p = this.options;
            if (!handler){
            	g.handler = $(p.target);
            }else{
            	g.handler = (typeof handler == 'string' ? $(handler, p.target) : handler);
            }    
        },
        _setTarget: function (target){
            this.target = $(target);
        },
        _setCursor: function (cursor){
            this.cursor = cursor;
            (this.proxy || this.handler).css('cursor', cursor);
        },
         _createProxy: function (proxy, e){
            if (!proxy){
            	 return;
            }
            var g = this, p = this.options;
            if (typeof proxy == 'function'){
                g.proxy = proxy.call(this.options.target, g, e);
            } else if (proxy == 'clone') {
                g.proxy = g.target.clone().css('position', 'absolute');
                g.proxy.appendTo('body');
            } else{
                g.proxy = $("<div class='l-draggable'></div>");
                g.proxy.width(g.target.width()).height(g.target.height())
                g.proxy.attr("dragid", g.id).appendTo('body');
            }
            g.proxy.css({
                left: p.proxyX == null ? g.current.left : g.current.startX + p.proxyX,
                top: p.proxyY == null ? g.current.top : g.current.startY + p.proxyY
            }).show();
        },
        _removeProxy: function (){
            var g = this;
            if (g.proxy){
                g.proxy.remove();
                g.proxy = null;
            }
        }
	});
})(jQuery);